package com.netty.modbus.server;

import com.netty.modbus.coder.OneDecoder;
import com.netty.modbus.coder.SecondDecoder;
import com.netty.modbus.handler.DataHandlerExample;
import com.netty.modbus.handler.InHandler;
import com.netty.modbus.handler.OutHandler;
import com.netty.modbus.trigger.ServerIdleStateTrigger;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.concurrent.TimeUnit;

/**
 * description: NettyServer <br>
 * date: 2021/9/30 15:56 <br>
 * @author: lwy <br>
 * @version: 1.0 <br>
 */
public class NettyServer {
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private int port;
    private static Channel serverChannel;
    private final ChannelGroup clientChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private InHandler inHandler;


    public NettyServer(int port,InHandler inHandler) {
        this.port = port;
        this.inHandler=inHandler;
    }
    public NettyServer() {
    }
    public void start(){
        //初始化连接管理线程池和工作线程池
        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //连接超时30000毫秒
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,30000)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new OneDecoder());
                            ch.pipeline().addLast(new SecondDecoder());
                            ch.pipeline().addLast("idleStateHandler",new IdleStateHandler(170, 0, 0, TimeUnit.SECONDS));
                            ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, -8, 0));
                            ch.pipeline().addLast(new OutHandler());
                            ch.pipeline().addLast(inHandler);
                            ch.pipeline().addLast(new ServerIdleStateTrigger());
                        }
                    });
            ChannelFuture f = b.bind(port).sync();
            // 设置监听
            serverChannel=f.channel();
            if(f.isSuccess()){
                System.out.println("启动服务器成功!");
            }else {
                System.out.println("启动服务器失败!");
            }
            //关闭服务监听
            f.channel().closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    workerGroup.shutdownGracefully();
                    bossGroup.shutdownGracefully();
                }
            }).sync();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**关闭服务*/
    public  void closeServer() {
        if (serverChannel != null) {
            serverChannel.close().awaitUninterruptibly();
            serverChannel = null;
        }
        clientChannels.close().awaitUninterruptibly();
    }

    /**获取所有客户端连接*/
    public ChannelGroup getClientChannels(){
        return clientChannels;
    }


}
